package mya.mes.mdc.logic.data.tag;

import mya.common.jpa.context.ServiceContext;
import mya.common.util.Utils;
import mya.mes.mdc.logic.plc.PlcTagTypeIdBuilder;
import mya.mes.mdc.logic.tag2.ExcelTagDataDef;
import mya.mes.mdc.model.data.MdcDataType;
import mya.mes.mdc.share.api.MdcModule;
import mya.mes.mdc.share.vo.MdcOptions;

import javax.persistence.criteria.CriteriaBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;

public class MdcDataTypeUpdater {

    public void update(ServiceContext context, List<ExcelTagDataDef> tagAlarmDefList) throws Exception {

        MdcOptions mdcOptions = MdcModule.getInstance().getMdcOptions();

        List<MdcDataType> dbList = loadAll(context);

        if (Utils.isNullOrEmpty(tagAlarmDefList)) {

            if (Utils.isNullOrEmpty(dbList)) {
                return;
            }

            for (MdcDataType plcTagType : dbList) {
                plcTagType.setActive(Boolean.FALSE);
            }

            return;
        }

        TreeMap<Long, MdcDataType> dbMap = new TreeMap<>();

        for (MdcDataType dbPlcTagType : dbList) {
            dbMap.put(dbPlcTagType.getObjectId(), dbPlcTagType);
        }

        List<MdcDataType> list = build(mdcOptions, tagAlarmDefList);
        try {
            for (MdcDataType plcTagType : list) {
                MdcDataType dbPlcTagType = dbMap.get(plcTagType.getObjectId());

                if (dbPlcTagType != null) {
                    //更新
                    copySrcToDest(plcTagType, dbPlcTagType);

                    updateArea(mdcOptions, plcTagType);
                    processUpdate(mdcOptions, dbPlcTagType);
                    dbMap.remove(plcTagType.getObjectId());
                } else {
                    //新增
                    context.em.persist(plcTagType);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }


        dbMap.values().forEach(dbPlcTagType -> {
            dbPlcTagType.setActive(Boolean.FALSE);
        });

    }

    protected void copySrcToDest(MdcDataType src, MdcDataType dest) {

        dest.setEnUs(src.getEnUs());

        dest.setZhCN(src.getZhCN());
    }


    private List<MdcDataType> loadAll(ServiceContext context) {
        String sql = "select o from  MdcDataType o ";
        CriteriaBuilder cb =
                context.em.getCriteriaBuilder();

        List<MdcDataType> list =
                context.em.createQuery(sql, MdcDataType.class).getResultList();

        return list;
    }


    private List<MdcDataType> build(MdcOptions mdcOptions, List<ExcelTagDataDef> tagAlarmDefList) throws Exception {
        List<MdcDataType> list = new ArrayList<>(tagAlarmDefList.size());


        String mdcTag = null;

        for (ExcelTagDataDef tagExcel : tagAlarmDefList) {


            mdcTag = tagExcel.tagName;

            if (mdcTag == null) {
                continue;
            }

            MdcDataType plcTagType = createPlcTagDef(mdcOptions, mdcTag, tagExcel);

            list.add(plcTagType);
        }

        return list;
    }


    private MdcDataType createPlcTagDef(MdcOptions mdcOptions, String mdcTag, ExcelTagDataDef tagExcel) throws InstantiationException, IllegalAccessException {

        MdcDataType plcTagType = new MdcDataType();
        plcTagType.setActive(Boolean.TRUE);


        String prefix = mdcTag.substring(0, 2).toUpperCase();

        int tagIndex = Integer.parseInt(mdcTag.substring(2));

        plcTagType.setMdcTag(mdcTag);
        plcTagType.setTagPrefix(prefix);
        plcTagType.setTagIndex(tagIndex);

        plcTagType.setBitIndex(0);


        plcTagType.setEnUs(tagExcel.description);
        plcTagType.setZhCN(tagExcel.description);


        long objectId = PlcTagTypeIdBuilder.buildId(prefix, tagIndex, 0);
        plcTagType.setObjectId(objectId);

        updateArea(mdcOptions, plcTagType);
        processCreate(mdcOptions, plcTagType);
        return plcTagType;
    }

    protected void processCreate(MdcOptions mdcOptions, MdcDataType plcTagType) {

    }

    protected void processUpdate(MdcOptions mdcOptions, MdcDataType plcTagType) {

    }


    protected void updateArea(MdcOptions mdcOptions, MdcDataType plcTagType) {
        if (plcTagType.getShop() == null) {
            plcTagType.setShop(mdcOptions.SHOP);
        }

        if (plcTagType.getArea() == null) {
            plcTagType.setArea(mdcOptions.AREA);
        }

        if (plcTagType.getSection() == null) {
            plcTagType.setSection(mdcOptions.SECTION);
        }

        if (plcTagType.getPoint() == null) {
            plcTagType.setPoint(mdcOptions.POINT);
        }
    }

}
